type Token = {
  type:'text'|'var'|'each'|'if'
  content:string
  children?:Token[]
  start?:number
  end?:number
}

class Scanner {
  pos = 0

  constructor(private text:string, private tail:string=text) {}

  skip(flag:string) {
    if(this.tail.indexOf(flag) === 0) {
      this.pos += flag.length
    }
  }

  scanUntil(stopFlag:string) {
    const start = this.pos

    while(!this.eof() && this.tail.indexOf(stopFlag) !== 0) {
      this.pos++
      this.tail = this.text.slice(this.pos)
    }
    
    return this.text.slice(start, this.pos)
  }

  eof() {
    return this.pos >= this.text.length
  }
}

class Stack<T> {
  private items: T[] = []


}

function nestTokens(tokens:Token[]):Token[] {
  const nestedTokens: Token[] = []

  for(const token of tokens) {
    switch(token.type) {
      
    }
  }


  return nestedTokens
}


function compile(tpl:string):Token[] {
  const tokens: Token[] = []
  const scanner = new Scanner(tpl)

  while(!scanner.eof()) {
    tokens.push({
      type:'text',
      content: scanner.scanUntil('{{')
    })
    scanner.skip('{{')
    const content = scanner.scanUntil('}}').trim()

    tokens.push({
      type: /^#\s*each/.test(content) ? 'each' : (/^#\s*if/.test(content) ? 'if' : 'var'),
      content:content.split(/\s+/, 2)[1] ?? content
    })

    scanner.skip('}}')
  }

  return tokens
}

function parse(tokens:Token[], data:object) {
}


export function render(tpl:string, data:object) {
  const tokens = compile(tpl.trim())

  console.log(nestTokens(tokens))

}


const tpl = /* html */`
<div>
  <h1>{{ title }}</h1>

  <ul>
    {{#each users }} 
      <li>{{ name }}</li>
      <li>{{ email }}</li>
      <li>{{ phone }}</li>
      <li>
        <ul>
          {{#each friends }}
           <li>{{ . }}</li>
          {{/each}}
        </ul>
      </li>
    {{/each}}
  </ul>

  <ol>
    {{#each colors}}
      <li>{{ . }}</li>
    {{/each}}
  </ol>

  {{#if login}} 
   <p>hello, admin</p>
  {{#else}} 
   <p>please login</p>
  {{/if}}
</div>
`

const data = {}

console.log(render(tpl, data))

